package com.csxh.web.userinfo.util;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 操作数组元素的工具类
 * 
 * @author 黎
 * @version 1.0
 */
public class ArrayUtil {

	/**
	 * 功能：输出指定数组中的所有元素
	 * 
	 * @version
	 * @param title
	 * @param 参数：args=被输出的数组，separator=各元素间的分隔符
	 * @return 返回：无
	 */
	public static void print(String title, int[] args, String... separators) {
		// TODO Auto-generated method stub
		// 判断数组参数是否有效
		if (null == args || args.length == 0) {
			return;
		}
		
		String separator=separators.length==0 ? " " : separators[0];
		
		System.out.print(title);
		// 输出除最后一个元素外所有元素
		for (int i = 0; i < args.length - 1; i++) {

			System.out.print(args[i] + separator);

		}
		// 再输出最后一个元素
		System.out.print(args[args.length - 1]);
	}

	/**
	 * 功能：输出指定数组中的所有元素，并换行
	 * 
	 * @version
	 * @param title
	 * @param 参数：args=被输出的数组，separator=各元素间的分隔符
	 * @return 返回：无
	 */
	public static void println(String title, int[] args, String... separators) {
		
		print(title, args, separators.length==0 ? " " : separators[0]);
		
		System.out.println();
	}

	/**
	 * 功能：输出指定数组中的所有元素
	 * 
	 * @version
	 * @param 参数：args=被输出的数组，separator=各元素间的分隔符
	 * @return 返回：无
	 */
	public static void print(int[] args, String separator) {

		print("", args, separator);

	}

	/**
	 * 功能：输出指定数组中的所有元素，并换行
	 * 
	 * @version
	 * @param 参数：args=被输出的数组，separator=各元素间的分隔符
	 * @return 返回：无
	 */
	public static void println(int[] args, String separator) {

		print("", args, separator);
		System.out.println();
	}

	/**
	 * 功能：输出指定数组中的所有元素
	 * 
	 * 参数：args=被输出的数组，separator=各元素间的分隔符 返回：无
	 */
	public static void print(String[] args, String separator) {

		// 判断数组参数是否有效
		if (null == args || args.length == 0) {
			return;
		}
		// 输出除最后一个元素外所有元素
		for (int i = 0; i < args.length - 1; i++) {

			System.out.print(args[i] + separator);

		}
		// 再输出最后一个元素
		System.out.print(args[args.length - 1]);
	}

	/**
	 * 在最后增加一个数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被增加的数组元素
	 * @return 返回增加后新数组
	 */
	public static String[] add(String elem, String[] args) {
		// 1、扩容
		int len = args.length;
		String[] args2 = new String[len + 1];
		// 2、复制原内容
		for (int i = 0; i < len; i++) {
			args2[i] = args[i];
		}
		// 3、插入新元素
		args2[len] = elem;
		// 4、返回新的数组
		return args2;

	}

	/**
	 * 在最后增加一个数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被增加的数组元素
	 * @return 返回增加后新数组
	 */
	public static int[] add(int elem, int[] args) {

		// 1、扩容
		int len = args.length;
		int[] args2 = new int[len + 1];
		// 2、复制原内容
		for (int i = 0; i < len; i++) {
			args2[i] = args[i];
		}
		// 3、插入新元素
		args2[len] = elem;
		// 4、返回新的数组
		return args2;

	}

	/**
	 * 在最后增加一个非重复的数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被增加的数组元素
	 * @return 返回增加后新数组
	 */
	public static int[] addIdentity(int elem, int[] args) {

		// 判断elem是否在args中
		int index = indexOf(elem, args);
		if (index > -1) {// 已经存在，不加入
			return args;
		}
		return add(elem, args);// 加入在最后面
	}

	/**
	 * 在指定位置插入一个数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被插入的数组元素
	 * @param index
	 *            被插入的索引号
	 * @return 返回增加后新数组
	 */
	public static int[] insertAt(int index, int elem, int[] args) {

		// 索引号合法性检测
		index = index < 0 ? 0 : index; // 最小索引=0
		index = index > args.length - 1 ? args.length - 1 : index;// 最大索引=args.length-1

		// 1、扩容
		int[] args2 = new int[args.length + 1];
		// 2、复制原数组的内容
		for (int i = 0; i < args.length; i++) {
			args2[i] = args[i];
		}
		// 3、移位腾空index位
		for (int i = args.length - 1; i >= index; i--) {
			args2[i + 1] = args2[i];// 将第i个元素，后移一位
		}
		// 4、在index位插入新元素
		args2[index] = elem;

		return args2;

	}

	/**
	 * 根据内容删除所有符条件的第一个数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被删除的数组元素
	 * @return 返回删除后新数组
	 */
	public static int[] deleteOne(int elem, int[] args) {

		// 找到索引号
		int index = indexOf(elem, args);
		// 删除指定索引数组元素
		return deleteAt(index, args);

	}

	/**
	 * 根据内容删除所有符条件的数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被删除的数组元素
	 * @return 返回删除后新数组
	 */
	public static int[] deleteAll(int elem, int[] args) {

		// 找到索引号
		int index = indexOf(elem, args);

		// 循环删除指定索引号的数组元素
		while (index > -1) {

			// 删除指定索引数组元素
			args = deleteAt(index, args);
			// 找到索引号
			index = indexOf(elem, args);

		}

		return args;

	}

	/**
	 * 删除指定索引数组元素
	 * 
	 * @param args
	 *            被操作原数组
	 * @param index
	 *            指定的索引号
	 * @return 返回被删除后的数组
	 */
	public static int[] deleteAt(int index, int[] args) {
		// 判断数组的合理性
		if (index < 0 || index >= args.length) {
			return args;
		}
		// 1、将index之后所有元素前移一位
		for (int i = index + 1; i < args.length; i++) {

			args[i - 1] = args[i];// 前移一位

		}
		// 2、创建一个新数组，其长度是原数组长度-1
		int[] args2 = new int[args.length - 1];
		// 3、将原数组前arg.length-1个元素复制到新数组
		for (int i = 0; i < args2.length; i++) {
			args2[i] = args[i];
		}

		return args2;

	}

	/**
	 * 获取指定元素的在数组中的第一次出现的索引号
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被查找的数组元素
	 * @return 返回索引号，如果返回 -1 表示没有找到
	 */
	public static int indexOf(int elem, int[] args) {

		for (int i = 0; i < args.length; i++) {
			if (args[i] == elem) {
				return i;
			}
		}
		return -1;

	}

	/**
	 * 获取指定元素的在数组中的最后一次出现的索引号
	 * 
	 * @param args
	 *            被操作原数组
	 * @param elem
	 *            被查找的数组元素
	 * @return 返回索引号，如果返回 -1 表示没有找到
	 */
	public static int lastIndexOf(int elem, int[] args) {

		for (int i = args.length - 1; i > -1; i--) {
			if (args[i] == elem) {
				return i;
			}
		}
		return -1;

	}

	/**
	 * 用随机构造一个整形数组 给定一个整数范围，创建由该范围的随机值填充的数组
	 * 
	 * @param m
	 *            范围的左边界值
	 * @param n
	 *            n>m 范围的右边界值
	 * @param count
	 *            数组的长度
	 * @return 新的随机数组
	 */
	public static int[] buildRandoms(int m, int n, int count) {
		// 创建返回的随机数组变量
		int[] rets = new int[count];
		for (int i = 0; i < rets.length; i++) {
			// 从[m,n]中取随机数
			rets[i] = MathUtil.random(m, n);
		}
		return rets;
	}

	/** 获取由n项组成的Fibonacci数组
	 * 
	 * @param n
	 * @return
	 */
	public static int[] buildFibonaccis(int n){
		
		int[] rets=new int[n];
		for (int i = 1; i <=n; i++) {
			rets[i-1]=MathUtil.fibonacciAt(i);
		}
		
		return rets;
	}
	
	/**
	 * 将原数组的内容复制到一个新的数组
	 * 
	 * @param args
	 * @return 新的数组
	 */
	public static int[] copyFrom(int[] args) {
		int[] rets = new int[args.length];
		for (int i = 0; i < rets.length; i++) {
			rets[i] = args[i];
		}
		return rets;
	}

	/**
	 * 对原数组进行指定方向（升，降）的排序
	 * 
	 * @param args
	 *            原数组
	 * @param asc
	 *            true=升排，false=降排
	 * @return 排序后的新数组
	 */
	public static int[] sort(int[] args, boolean asc) {// desc

		// 1、复制原数组
		int[] rets = copyFrom(args);
		// 2、使用冒泡排序算法
		
		for (int i = 0; i < rets.length; i++) {

			for (int j = i+1; j < rets.length; j++) {
				
				 if (asc) {//升排
					 if (rets[i]>rets[j]) {
						  int t=rets[i];
						  rets[i]=rets[j];
						  rets[j]=t;
					 }   	
				 }else{//降排
					 if (rets[i]<rets[j]) {
						  int t=rets[i];
						  rets[i]=rets[j];
						  rets[j]=t;
					 }
				 }
                 
			}
		}

		return rets;
	}

	/**
	 * 求数组中的最大值
	 * @param args
	 * @return
	 */
	public static int max(int[] args){
		int ret=Integer.MIN_VALUE;
		
		for (int i = 0; i < args.length; i++) {
			if (args[i]>ret) {
				ret=args[i];
			}
		}
		
		return ret;
	}
	/**
	 * 求数组中的最小值
	 * @param args
	 * @return
	 */
	public static int min(int[] args){
		int ret=Integer.MAX_VALUE;
		
		for (int i = 0; i < args.length; i++) {
			if (args[i]<ret) {
				ret=args[i];
			}
		}
		
		return ret;
	}
	/**
	 * 对数组求和
	 * @param args
	 * @return
	 */
	public static int sum(int[] args){
		
		int ret=0;
		
		for (int i = 0; i < args.length; i++) {
			ret+=args[i];
		}
		
		return ret;
		
	}
	
	//裁剪所有指定的元素
	public static int[] trimAll(int[] args,int... elems){
		
		int[] rets=copyFrom(args);
		
		for (int i = 0; i < elems.length; i++) {
			rets=deleteAll(elems[i], rets);
		}
		
		return rets;
	}
	//裁剪首次出现的指定元素
	public static int[] trimOne(int[] args,int... elems){
		
		int[] rets=copyFrom(args);
		
		for (int i = 0; i < elems.length; i++) {
			rets=deleteOne(elems[i], rets);
		}
		
		return rets;
	}
	
	/**
	 * 获取一个数组的子数组
	 * @param start
	 * @param end 不包含end start<end
	 * @param args
	 * @return
	 */
	public static int[] sub(int start,int end,int[] args){
		
		//限制end的上限值
		end=end>args.length ? args.length : end;
		
		int[] rets=new int[end-start];
		int index=0;
		for(int i=start;i<end;i++,index++){
			rets[index]=args[i];
		} 
		return rets;
	}
	
	/**
	 * 获取一个数组的子数组
	 * @param start
	 * @param args
	 * @return
	 */
	public static int[] sub(int start,int[] args){
		
		return sub(start,args.length,args);
	}

	
	public  static <T> boolean contains(T elem,T[] array){
		
		for (T t : array) {
			boolean b=((Object)t).equals((Object)elem);
			if (b) {
				return true;
			}
		}
		return false;
		
	}
	
	public  static <T> List<T> toList(T[] array){
		List<T> list=new ArrayList<>();
		for (T t : array) {
			list.add(t);
		}
		return list;		
	}

	public  static <T> List<T> toList2(T... array){
		List<T> list=new ArrayList<>();
		for (T t : array) {
			list.add(t);
		}
		return list;		
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T[] toArray(List<T> list){
		assert(null!=list && list.size()>0);
		T[] a=(T[])Array.newInstance(list.get(0).getClass(), list.size());
		return list.toArray(a);
	}
	
}
